<?php

namespace app\adminapi\service;

use app\adminapi\model\sysmenu\SysMenuDO;
use app\adminapi\model\sysuser\SysUserDO;
use app\common\exception\OtherException;
use app\common\utils\SysUtil;

class SysMenuService
{
    public function getTreeSysMenu()
    {
        $sysMenuDOS = [];
        $userId = request()->adminId;
        // 校验用户是否可用
        $this->validUserAvailable($userId);
        // 获取用户信息
        $sysUserDO = (new SysUserDO())
            ->where('user_id', $userId)
            ->find();
        // 构造查询条件
        $where = [
            ['status', '=', 0],
            ['menu_type', '<>', 'F']
        ];
        // 处理超级管理员用户
        if ($sysUserDO->isRoot == 1) {
            $sysMenuDOS = (new SysMenuDO())->where($where)->select()->toArray();
        } else {
            // 获取角色信息
            $userRole = (new SysUserRoleService())->getSysUserRole($userId);
            // 获取角色菜单信息
            $sysRoleMenu = (new SysRoleMenuService())->getSysRoleMenuByRoleId($userRole->roleId);
            $where[] = ['menu_id', 'in', explode(',', $sysRoleMenu->menuIds)];
            $sysMenuDOS = (new SysMenuDO())->where($where)->select()->toArray();
        }
        return SysUtil::generateRouter($sysMenuDOS);
    }

    public function getUserPermissions(int $userId): array
    {
        $permsList = array();
        $this->validUserAvailable($userId);
        $info = (new SysUserDO())->where('user_id', $userId)->find();
        // 处理超管权限
        if ($info->isRoot == 1) {
            $permsList = ['*'];
        } else {
            $where = [
                ['status', '=', 0],
                ['menu_type', '=', 'F']
            ];
            // 获取角色信息
            $userRole = (new SysUserRoleService())->getSysUserRole($userId);
            // 获取角色菜单信息
            $sysRoleMenu = (new SysRoleMenuService())->getSysRoleMenuByRoleId($userRole->roleId);
            $where[] = ['menu_id', 'in', explode(',', $sysRoleMenu->menuIds)];
            // 根据当前用户分配的角色查询
            $permissionList = (new SysMenuDO())->where($where)->select()->toArray();
            foreach ($permissionList as $item) {
                $permsList[] = $item['perms'];
            }
        }
        return $permsList;
    }

    public function getSysMenuListWithoutAction(): array
    {
        $where[] = ['menu_type', '<>', 'F'];
        $sysMenuDOS = (new SysMenuDO())->where($where)->select()->toArray();
        return SysUtil::generateRouter($sysMenuDOS);
    }

    public function getSysMenuAllList(): array
    {
        $sysMenuDOS = (new SysMenuDO())->select()->toArray();
        return SysUtil::generateRoleMenuTree($sysMenuDOS);
    }

    public function addSysMenu(array $sysMenuDO)
    {
        if ($sysMenuDO['path'] != '') {
            $this->validMenuPathExist($sysMenuDO['path'], []);
        }
        SysMenuDO::create($sysMenuDO);
    }

    public function getSysMenu(int $menuId)
    {
        $this->validExist($menuId);
        return (new SysMenuDO())->where('menu_id', $menuId)->find();
    }

    public function deleteSysMenu(int $menuId): bool
    {
        $this->validExist($menuId);
        $this->validChildExist($menuId);
        return SysMenuDO::destroy($menuId);
    }

    public function updateSysMenu(array $sysMenuDO)
    {
        $oldMenu = (new SysMenuDO())->where('menu_id', $sysMenuDO['menuId'])->find();
        $this->validExist($sysMenuDO['menuId']);
        if (('F' != $sysMenuDO['menuType']) && !empty($sysMenuDO['path'])) {
            $this->validMenuPathExist($sysMenuDO['path'], $oldMenu);
        }
        return SysMenuDO::update($sysMenuDO);
    }

    public function getAllActionByMenuId(int $menuId): array
    {
        $this->validExist($menuId);
        $where = [
            ['parent_id', '=', $menuId],
            ['status', '=', 0],
            ['menu_type', '=', 'F']
        ];
        return (new SysMenuDO())->where($where)->select()->toArray();
    }

    private function validUserAvailable(int $userId)
    {
        $exist = (new SysUserDO())
            ->where('user_id', $userId)
            ->find();
        if (empty($exist)) {
            throw new OtherException('用户不存在');
        } else {
            if ($exist->status == 1) {
                throw new OtherException('用户已被禁用');
            }
        }
    }

    // 校验菜单路径是否存在
    private function validMenuPathExist(string $newPath, $sysMenuDO)
    {
        $where[] = ['path', '=', $newPath];
        $exist = (new SysMenuDO())->where($where)->find();
        if (!empty($exist)) {
            if (!empty($sysMenuDO)) {
                if ($exist['menuId'] != $sysMenuDO['menuId']) {
                    throw new OtherException('路由地址已存在');
                }
            } else {
                throw new OtherException('路由地址已存在');
            }
        }
    }

    private function validExist(int $menuId)
    {
        $exist = (new SysMenuDO())->where('menu_id', $menuId)->find();
        if (empty($exist)) {
            throw new OtherException('菜单不存在');
        }
    }

    private function validChildExist(int $parentId)
    {
        $where[] = ['parent_id', '=', $parentId];
        $exist = (new SysMenuDO())->where($where)->select();
        if (!$exist->isEmpty()) {
            throw new OtherException('存在子菜单禁止删除');
        }
    }
}